package cn.shujuhai.meeting.service.impl;

import cn.dev33.satoken.stp.StpUtil;
import cn.shujuhai.common.domain.DepartmentMeet;
import cn.shujuhai.common.domain.DepartmentUser;
import cn.shujuhai.common.domain.SysUser;
import cn.shujuhai.common.mapper.SysUserMapper;
import cn.shujuhai.common.pluging.data.ResultCode;
import cn.shujuhai.common.pluging.data.ResultVo;
import cn.shujuhai.common.service.DepartmentMeetService;
import cn.shujuhai.common.service.DepartmentUserService;
import cn.shujuhai.common.service.SysUserService;
import cn.shujuhai.meeting.config.CustomCellWriteHeightConfig;
import cn.shujuhai.meeting.config.CustomCellWriteWidthConfig;
import cn.shujuhai.meeting.domain.*;
import cn.shujuhai.meeting.mapper.ReservationMapper;
import cn.shujuhai.meeting.service.*;
import com.alibaba.excel.EasyExcel;
import com.alibaba.excel.support.ExcelTypeEnum;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.github.pagehelper.PageInfo;
import jakarta.servlet.http.HttpServletResponse;
import lombok.RequiredArgsConstructor;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.io.IOException;
import java.net.URLEncoder;
import java.nio.charset.StandardCharsets;
import java.time.DayOfWeek;
import java.time.LocalDate;
import java.time.LocalTime;
import java.time.format.DateTimeFormatter;
import java.util.*;
import java.util.concurrent.ConcurrentHashMap;
import java.util.stream.Collectors;

@Service
@RequiredArgsConstructor
public class ReservationServiceImpl extends ServiceImpl<ReservationMapper, Reservation> implements ReservationService {
    // 使用一个 Map 来存储每个用户的预约集合
    private final Map<Long, Set<FrequencyVo>> userReservations = new ConcurrentHashMap<>();
    private final DepartmentMeetService departmentMeetService;
    private final MeetingRoomsService meetingRoomsService;
    private final MeetReservationService meetReservationService;
    private final DepartmentUserService departmentUserService;
    private final EquipmentService equipmentService;
    private final MeetEquipmentService meetEquipmentService;
    private final SysUserService sysUserService;
    private final SysUserMapper sysUserMapper;

    /**
     * 获取当前用户的预约集合
     *
     * @return 当前用户的预约集合
     */
    private Set<FrequencyVo> getCurrentUserReservations() {
        long loginIdAsLong = StpUtil.getLoginIdAsLong();
        return this.userReservations.computeIfAbsent(loginIdAsLong, k -> new HashSet<>());
    }

    /**
     * 添加预约
     *
     * @param reservation 预约信息
     * @param roomId      会议室ID
     * @return 操作结果
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public ResultVo<?> add(List<Reservation> reservation, Long roomId) {
        long loginIdAsLong = StpUtil.getLoginIdAsLong();
        Set<FrequencyVo> reservations = getCurrentUserReservations();
        reservations.clear();

        if (!this.saveBatch(reservation)) {
            return ResultVo.failure(ResultCode.FAILED);
        }

        // 获取所有保存成功的预约的 ID
        List<Long> reservationIds = reservation.stream()
                .map(Reservation::getReservationId)
                .toList();

        // 为每个预约创建一个 MeetReservation 记录
        List<MeetReservation> meetReservations = reservationIds.stream()
                .map(reservationId -> {
                    MeetReservation meetReservation = new MeetReservation();
                    meetReservation.setReservationId(reservationId);
                    meetReservation.setUserId(loginIdAsLong);
                    meetReservation.setRoomId(roomId);
                    return meetReservation;
                })
                .collect(Collectors.toList());

        // 保存 MeetReservation 记录
        if (!this.meetReservationService.saveBatch(meetReservations)) {
            return ResultVo.failure(ResultCode.FAILED);
        }
        return ResultVo.success();
    }

    /**
     * 查询数据库中的预约集合
     *
     * @param roomId 会议室ID
     * @return 查询的预约集合
     */
    public Set<FrequencyVo> getExistingReservations(Long roomId) {
        long loginIdAsLong = StpUtil.getLoginIdAsLong();
        // 构造查询条件
        QueryWrapper<MeetReservation> query = new QueryWrapper<>();
        query.eq("user_id", loginIdAsLong);
        query.eq("room_id", roomId);
        // 执行查询
        List<MeetReservation> meetReservations = this.meetReservationService.list(query);

        // 提取 reservationId
        List<Long> reservationIds = meetReservations.stream()
                .map(MeetReservation::getReservationId)
                .toList();
        if (reservationIds.isEmpty()) {
            return Collections.emptySet();
        }
        // 使用 MyBatis-Plus 查询构造器
        QueryWrapper<Reservation> queryWrapper = new QueryWrapper<>();
        queryWrapper.select("reservation_data", "start_time", "end_time");
        queryWrapper.in("reservation_id", reservationIds);
        // 执行查询
        List<Reservation> reservations = this.list(queryWrapper);
        DateTimeFormatter timeFormatter = DateTimeFormatter.ofPattern("HH:mm:ss");
        // 将查询结果转换为 FrequencyVo 集合
        return reservations.stream().map(reservation -> {
            FrequencyVo frequencyVo = new FrequencyVo();
            frequencyVo.setReservationData(String.valueOf(reservation.getReservationData()));
            frequencyVo.setStartTime(reservation.getStartTime().format(timeFormatter));
            frequencyVo.setEndTime(reservation.getEndTime().format(timeFormatter));
            return frequencyVo;
        }).collect(Collectors.toSet());
    }

    /**
     * 检查预约频次是否冲突
     *
     * @param frequencyVo 预约频次信息
     * @param roomId      会议室ID
     * @return 返回包含所有可能预约的Set集合或冲突信息
     */
    @Override
    public ResultVo<Set<FrequencyVo>> check(FrequencyVo frequencyVo, Long roomId) {
        // 解析日期格式
        DateTimeFormatter dateFormatter = DateTimeFormatter.ofPattern("yyyy-MM-dd");
        DateTimeFormatter timeFormatter = DateTimeFormatter.ofPattern("HH:mm:ss");

        // 解析预约日期和开始结束时间
        LocalDate reservationDate = LocalDate.parse(frequencyVo.getReservationData(), dateFormatter);
        LocalTime startTime = LocalTime.parse(frequencyVo.getStartTime(), timeFormatter);
        LocalTime endTime = LocalTime.parse(frequencyVo.getEndTime(), timeFormatter);

        // 解析重复结束日期（如果存在）
        LocalDate repeatEndDate = frequencyVo.getRepeatEndData() != null && !frequencyVo.getRepeatEndData().isEmpty() ?
                LocalDate.parse(frequencyVo.getRepeatEndData(), dateFormatter) : null;

        // 根据repeatType生成所有可能的日期
        Set<FrequencyVo> generatedFrequencies = new HashSet<>();
        switch (frequencyVo.getRepeatType()) {
            case 0: // 一次
                generatedFrequencies.add(frequencyVo);
                break;
            case 1: // 每天
                generatedFrequencies.addAll(generateDailyRepeats(reservationDate, repeatEndDate, startTime, endTime, frequencyVo.getRepeatType()));
                break;
            case 2: // 每个工作日
                generatedFrequencies.addAll(generateWorkdayRepeats(reservationDate, repeatEndDate, startTime, endTime, frequencyVo.getRepeatType()));
                break;
            case 3: // 每周几
                generatedFrequencies.addAll(generateWeeklyRepeats(reservationDate, repeatEndDate, startTime, endTime, frequencyVo.getDay(), frequencyVo.getRepeatType()));
                break;
            case 4: // 每月第几天
                generatedFrequencies.addAll(generateMonthlyRepeats(reservationDate, repeatEndDate, startTime, endTime, frequencyVo.getDay(), frequencyVo.getRepeatType()));
                break;
            default:
                throw new IllegalArgumentException("Unsupported repeat type: " + frequencyVo.getRepeatType());
        }

        // 检查生成的预约是否与现有预约冲突
        for (FrequencyVo newFrequencyVo : generatedFrequencies) {
            FrequencyVo conflictingReservation = checkTimeOverlap(newFrequencyVo, getExistingReservations(roomId));
            if (conflictingReservation != null) {
                return ResultVo.failure(ResultCode.RESERVATION_EXITS, Collections.singleton(conflictingReservation));
            }

            conflictingReservation = checkTimeOverlap(newFrequencyVo, getCurrentUserReservations());
            if (conflictingReservation != null) {
                return ResultVo.failure(ResultCode.RESERVATION_CT);
            }
        }

        // 如果没有冲突，将生成的预约添加到当前用户的预约集合中
        getCurrentUserReservations().addAll(generatedFrequencies);
        return ResultVo.success(getCurrentUserReservations());
    }

    /**
     * 生成每天重复的预约
     *
     * @param startDate     开始日期
     * @param repeatEndDate 结束日期
     * @param startTime     开始时间
     * @param endTime       结束时间
     * @param repeatType    重复类型
     * @return 返回包含所有可能预约的Set集合
     */
    private Set<FrequencyVo> generateDailyRepeats(LocalDate startDate, LocalDate repeatEndDate, LocalTime startTime, LocalTime endTime, int repeatType) {
        Set<FrequencyVo> generatedFrequencies = new HashSet<>();
        LocalDate currentDate = startDate;
        while (repeatEndDate == null || !currentDate.isAfter(repeatEndDate)) {
            FrequencyVo newFrequencyVo = createFrequencyVo(currentDate, startTime, endTime, repeatEndDate, repeatType);
            generatedFrequencies.add(newFrequencyVo);
            currentDate = currentDate.plusDays(1);
        }
        return generatedFrequencies;
    }

    /**
     * 生成每个工作日重复的预约
     *
     * @param startDate     开始日期
     * @param repeatEndDate 结束日期
     * @param startTime     开始时间
     * @param endTime       结束时间
     * @param repeatType    重复类型
     * @return 返回包含所有可能预约的Set集合
     */
    private Set<FrequencyVo> generateWorkdayRepeats(LocalDate startDate, LocalDate repeatEndDate, LocalTime startTime, LocalTime endTime, int repeatType) {
        Set<FrequencyVo> generatedFrequencies = new HashSet<>();
        LocalDate currentDate = startDate;
        while (repeatEndDate == null || !currentDate.isAfter(repeatEndDate)) {
            if (currentDate.getDayOfWeek() != DayOfWeek.SATURDAY && currentDate.getDayOfWeek() != DayOfWeek.SUNDAY) {
                FrequencyVo newFrequencyVo = createFrequencyVo(currentDate, startTime, endTime, repeatEndDate, repeatType);
                generatedFrequencies.add(newFrequencyVo);
            }
            currentDate = currentDate.plusDays(1);
        }
        return generatedFrequencies;
    }

    /**
     * 生成每周几重复的预约
     *
     * @param startDate     开始日期
     * @param repeatEndDate 结束日期
     * @param startTime     开始时间
     * @param endTime       结束时间
     * @param dayOfWeek     星期几（0表示周日，1表示周一，依此类推）
     * @param repeatType    重复类型
     * @return 返回包含所有可能预约的Set集合
     */
    private Set<FrequencyVo> generateWeeklyRepeats(LocalDate startDate, LocalDate repeatEndDate, LocalTime startTime, LocalTime endTime, Integer dayOfWeek, int repeatType) {
        Set<FrequencyVo> generatedFrequencies = new HashSet<>();
        LocalDate currentDate = startDate;
        while (repeatEndDate == null || !currentDate.isAfter(repeatEndDate)) {
            if (currentDate.getDayOfWeek().getValue() == dayOfWeek) {
                FrequencyVo newFrequencyVo = createFrequencyVo(currentDate, startTime, endTime, repeatEndDate, repeatType);
                generatedFrequencies.add(newFrequencyVo);
            }
            currentDate = currentDate.plusDays(1);
        }
        return generatedFrequencies;
    }

    /**
     * 生成每月第几天重复的预约
     *
     * @param startDate     开始日期
     * @param repeatEndDate 结束日期
     * @param startTime     开始时间
     * @param endTime       结束时间
     * @param dayOfMonth    每月的第几天（1到31）
     * @param repeatType    重复类型
     * @return 返回包含所有可能预约的Set集合
     */
    private Set<FrequencyVo> generateMonthlyRepeats(LocalDate startDate, LocalDate repeatEndDate, LocalTime startTime, LocalTime endTime, Integer dayOfMonth, int repeatType) {
        Set<FrequencyVo> generatedFrequencies = new HashSet<>();
        LocalDate currentDate = startDate;
        while (repeatEndDate == null || !currentDate.isAfter(repeatEndDate)) {
            if (currentDate.getDayOfMonth() == dayOfMonth) {
                FrequencyVo newFrequencyVo = createFrequencyVo(currentDate, startTime, endTime, repeatEndDate, repeatType);
                generatedFrequencies.add(newFrequencyVo);
            }
            currentDate = currentDate.plusDays(1);
        }
        return generatedFrequencies;
    }

    /**
     * 检查时间交集冲突
     *
     * @param newFrequencyVo 新的预约频次信息
     * @param set            存储预约的集合
     * @return 如果存在时间交集，返回冲突的预约信息；否则返回null
     */
    private FrequencyVo checkTimeOverlap(FrequencyVo newFrequencyVo, Set<FrequencyVo> set) {
        // 遍历内存中的预约
        for (FrequencyVo existingVo : set) {
            // 如果日期不同，直接跳过时间交集的检查
            if (!existingVo.getReservationData().equals(newFrequencyVo.getReservationData())) {
                continue;
            }

            // 如果日期相同，检查时间交集
            if (isTimeOverlap(existingVo.getStartTime(), existingVo.getEndTime(), newFrequencyVo.getStartTime(), newFrequencyVo.getEndTime())) {
                return existingVo; // 存在时间交集
            }
        }
        return null; // 不存在时间交集
    }

    /**
     * 检查两个时间范围是否有交集
     *
     * @param startTime1 第一个时间范围的开始时间
     * @param endTime1   第一个时间范围的结束时间
     * @param startTime2 第二个时间范围的开始时间
     * @param endTime2   第二个时间范围的结束时间
     * @return 如果两个时间范围有交集，返回true；否则返回false
     */
    private boolean isTimeOverlap(String startTime1, String endTime1, String startTime2, String endTime2) {
        DateTimeFormatter timeFormatter = DateTimeFormatter.ofPattern("HH:mm:ss");
        LocalTime start1 = LocalTime.parse(startTime1, timeFormatter);
        LocalTime end1 = LocalTime.parse(endTime1, timeFormatter);
        LocalTime start2 = LocalTime.parse(startTime2, timeFormatter);
        LocalTime end2 = LocalTime.parse(endTime2, timeFormatter);

        // 检查两个时间范围是否有交集
        return !end1.isBefore(start2) && !start1.isAfter(end2);
    }

    /**
     * 创建并初始化一个新的FrequencyVo对象
     *
     * @param reservationDate 预约日期
     * @param startTime       开始时间
     * @param endTime         结束时间
     * @param repeatEndData   重复结束日期
     * @param repeatType      重复类型
     * @return 初始化后的FrequencyVo对象
     */
    private FrequencyVo createFrequencyVo(LocalDate reservationDate, LocalTime startTime, LocalTime endTime, LocalDate repeatEndData, int repeatType) {
        FrequencyVo newFrequencyVo = new FrequencyVo();
        newFrequencyVo.setReservationData(reservationDate.toString());
        DateTimeFormatter timeFormatter = DateTimeFormatter.ofPattern("HH:mm:ss");
        newFrequencyVo.setStartTime(startTime.format(timeFormatter));
        newFrequencyVo.setEndTime(endTime.format(timeFormatter));
        newFrequencyVo.setRepeatType(repeatType);
        newFrequencyVo.setRepeatEndData(repeatEndData != null ? repeatEndData.toString() : null);
        return newFrequencyVo;
    }

    @Override
    public ResultVo<?> getMeetByDepartment(Long departmentId) {
        // 1. 获取部门关联的会议室ID列表
        List<DepartmentMeet> departmentMeetList = this.departmentMeetService.list(
                new QueryWrapper<DepartmentMeet>().lambda()
                        .eq(DepartmentMeet::getDepartmentId, departmentId)
        );
        List<Long> roomIds = departmentMeetList.stream()
                .map(DepartmentMeet::getRoomId)
                .distinct()
                .collect(Collectors.toList());

        if (roomIds.isEmpty()) {
            return ResultVo.success(Collections.emptyList());
        }

        // 2. 查询会议室详情
        List<MeetingRooms> meetingRooms = this.meetingRoomsService.list(
                new QueryWrapper<MeetingRooms>()
                        .in("room_id", roomIds)  // 按ID列表查询
                        .ne("status", "close")   // 排除状态为close的会议室
        );

        // 3. 通过中间表查询设备关联关系
        List<MeetEquipment> meetEquipments = this.meetEquipmentService.list(
                new QueryWrapper<MeetEquipment>().lambda()
                        .in(MeetEquipment::getRoomId, roomIds)
        );

        // 4. 提取所有设备ID并查询设备详情
        List<Long> equipmentIds = meetEquipments.stream()
                .map(MeetEquipment::getEquipmentId)
                .distinct()
                .collect(Collectors.toList());
        if (!equipmentIds.isEmpty()) {
            List<Equipment> equipmentList = this.equipmentService.listByIds(equipmentIds);

            // 5. 构建设备名称Map（roomId -> 设备名称集合）
            Map<Long, Set<String>> deviceNameMap = new HashMap<>();
            for (MeetEquipment me : meetEquipments) {
                Long roomId = me.getRoomId();
                Long equipmentId = me.getEquipmentId();

                // 查找设备名称
                String equipmentName = equipmentList.stream()
                        .filter(eq -> eq.getEquipmentId().equals(equipmentId))
                        .map(Equipment::getEquipmentName)
                        .findFirst()
                        .orElse("未知设备");

                deviceNameMap.computeIfAbsent(roomId, k -> new HashSet<>()).add(equipmentName);
            }

            // 6. 赋值给会议室对象
            for (MeetingRooms room : meetingRooms) {
                // 使用getOrDefault确保每个会议室都有设备名称集合，即使为空
                Set<String> equipmentNames = deviceNameMap.getOrDefault(room.getRoomId(), new HashSet<>());
                room.setEquipmentNameList(new ArrayList<>(equipmentNames));
            }
        } else {
            meetingRooms.forEach(room -> room.setEquipmentNameList(new ArrayList<>()));
        }
        return ResultVo.success(meetingRooms);
    }

    @Override
    public ResultVo<Set<FrequencyVo>> removeReservation(FrequencyVo frequencyVo) {
        Set<FrequencyVo> reservations = getCurrentUserReservations();

        // 根据repeatType生成所有可能的日期
        Set<FrequencyVo> toRemove = new HashSet<>();
        switch (frequencyVo.getRepeatType()) {
            case 0: // 一次
                toRemove.add(frequencyVo);
                break;
            case 1: // 每天
                toRemove.addAll(generateDailyRepeats(
                        LocalDate.parse(frequencyVo.getReservationData(), DateTimeFormatter.ofPattern("yyyy-MM-dd")),
                        frequencyVo.getRepeatEndData() != null ? LocalDate.parse(frequencyVo.getRepeatEndData(), DateTimeFormatter.ofPattern("yyyy-MM-dd")) : null,
                        LocalTime.parse(frequencyVo.getStartTime(), DateTimeFormatter.ofPattern("HH:mm:ss")),
                        LocalTime.parse(frequencyVo.getEndTime(), DateTimeFormatter.ofPattern("HH:mm:ss")),
                        frequencyVo.getRepeatType()
                ));
                break;
            case 2: // 每个工作日
                toRemove.addAll(generateWorkdayRepeats(
                        LocalDate.parse(frequencyVo.getReservationData(), DateTimeFormatter.ofPattern("yyyy-MM-dd")),
                        frequencyVo.getRepeatEndData() != null ? LocalDate.parse(frequencyVo.getRepeatEndData(), DateTimeFormatter.ofPattern("yyyy-MM-dd")) : null,
                        LocalTime.parse(frequencyVo.getStartTime(), DateTimeFormatter.ofPattern("HH:mm:ss")),
                        LocalTime.parse(frequencyVo.getEndTime(), DateTimeFormatter.ofPattern("HH:mm:ss")),
                        frequencyVo.getRepeatType()
                ));
                break;
            case 3: // 每周几
                toRemove.addAll(generateWeeklyRepeats(
                        LocalDate.parse(frequencyVo.getReservationData(), DateTimeFormatter.ofPattern("yyyy-MM-dd")),
                        frequencyVo.getRepeatEndData() != null ? LocalDate.parse(frequencyVo.getRepeatEndData(), DateTimeFormatter.ofPattern("yyyy-MM-dd")) : null,
                        LocalTime.parse(frequencyVo.getStartTime(), DateTimeFormatter.ofPattern("HH:mm:ss")),
                        LocalTime.parse(frequencyVo.getEndTime(), DateTimeFormatter.ofPattern("HH:mm:ss")),
                        frequencyVo.getDay(),
                        frequencyVo.getRepeatType()
                ));
                break;
            case 4: // 每月第几天
                toRemove.addAll(generateMonthlyRepeats(
                        LocalDate.parse(frequencyVo.getReservationData(), DateTimeFormatter.ofPattern("yyyy-MM-dd")),
                        frequencyVo.getRepeatEndData() != null ? LocalDate.parse(frequencyVo.getRepeatEndData(), DateTimeFormatter.ofPattern("yyyy-MM-dd")) : null,
                        LocalTime.parse(frequencyVo.getStartTime(), DateTimeFormatter.ofPattern("HH:mm:ss")),
                        LocalTime.parse(frequencyVo.getEndTime(), DateTimeFormatter.ofPattern("HH:mm:ss")),
                        frequencyVo.getDay(),
                        frequencyVo.getRepeatType()
                ));
                break;
            default:
                throw new IllegalArgumentException("Unsupported repeat type: " + frequencyVo.getRepeatType());
        }

        // 从当前用户的预约集合中删除所有生成的日期
        reservations.removeAll(toRemove);

        // 检查是否删除成功
        if (reservations.stream().noneMatch(toRemove::contains)) {
            return ResultVo.success(reservations);
        } else {
            return ResultVo.failure(ResultCode.RESERVATION_NOT_FOUND);
        }
    }

    @Override
    public ResultVo<?> clear() {
        long loginIdAsLong = StpUtil.getLoginIdAsLong();
        this.userReservations.remove(loginIdAsLong);
        return ResultVo.success();
    }

    @Override
    public ResultVo<?> reservationListByUserIdAndRoomId(Long roomId) {
        // 构造查询条件
        QueryWrapper<MeetReservation> query = new QueryWrapper<>();
        query.eq("room_id", roomId);
        // 执行查询
        List<MeetReservation> meetReservations = this.meetReservationService.list(query);

        // 如果没有预约记录，直接返回空结果
        if (meetReservations.isEmpty()) {
            return ResultVo.success(Collections.emptyList());
        }

        // 提取 reservationId 和对应的 userId
        Map<Long, Long> reservationIdToUserIdMap = meetReservations.stream()
                .collect(Collectors.toMap(MeetReservation::getReservationId, MeetReservation::getUserId));

        // 提取所有 reservationId
        List<Long> reservationIds = reservationIdToUserIdMap.keySet().stream().toList();

        // 根据 reservationIds 查询预约记录
        List<Reservation> reservationList = this.list(new QueryWrapper<Reservation>().lambda()
                .in(Reservation::getReservationId, reservationIds));

        // 提取所有 userId
        List<Long> userIds = reservationIdToUserIdMap.values().stream().distinct().toList();

        // 根据 userIds 查询用户信息
        List<SysUser> userList = this.sysUserService.list(new QueryWrapper<SysUser>().lambda()
                .in(SysUser::getUserId, userIds)
                .select(SysUser::getUserId, SysUser::getUsername, SysUser::getPhone));

        // 将用户信息存储到 Map 中，以便快速查找
        Map<Long, SysUser> userMap = userList.stream()
                .collect(Collectors.toMap(SysUser::getUserId, user -> user));

        // 将用户信息与预约记录关联
        for (Reservation reservation : reservationList) {
            Long userId = reservationIdToUserIdMap.get(reservation.getReservationId());
            SysUser user = userMap.get(userId);
            if (user != null) {
                reservation.setUsername(user.getUsername());
                reservation.setPhone(user.getPhone());
            }
        }

        return ResultVo.success(reservationList);
    }

    @Override
    public ResultVo<?> getMeetByUserId() {
        List<DepartmentUser> departmentUserList = this.departmentUserService.list(new QueryWrapper<DepartmentUser>().lambda().eq(DepartmentUser::getUserId, StpUtil.getLoginIdAsLong()));
        if (departmentUserList.isEmpty()) {
            return ResultVo.failure(ResultCode.FAILED);
        }
        List<Long> list = departmentUserList.stream()
                .map(DepartmentUser::getDepartmentId)
                .toList();
        List<Long> list1 = this.departmentMeetService.list(new QueryWrapper<DepartmentMeet>().lambda().in(DepartmentMeet::getDepartmentId, list))
                .stream()
                .map(DepartmentMeet::getRoomId)
                .toList();
        List<MeetingRooms> meetingRooms = this.meetingRoomsService.listByIds(list1);
        return ResultVo.success(meetingRooms);
    }

    @Override
    public ResultVo<PageInfo<Reservation>> getList(Reservation reservation, Integer pageNum, Integer pageSize) {
        List<Reservation> allReservations = reservationListByUserId();
        // 根据前端传来的条件筛选符合条件的预约信息
        List<Reservation> filteredReservations = allReservations.stream()
                .filter(r -> (reservation.getPurpose() == null || r.getPurpose().contains(reservation.getPurpose()))
                        && (reservation.getReservationData() == null || (r.getReservationData() != null && r.getReservationData().equals(reservation.getReservationData())))
                        && (reservation.getStartTime() == null || (r.getStartTime() != null && r.getStartTime().equals(reservation.getStartTime())))
                        && (reservation.getRepeatType() == null || (r.getRepeatType() != null && r.getRepeatType().equals(reservation.getRepeatType())))
                        && (reservation.getEndTime() == null || (r.getEndTime() != null && r.getEndTime().equals(reservation.getEndTime())))
                        && (reservation.getRepeatEndData() == null || (r.getRepeatEndData() != null && r.getRepeatEndData().equals(reservation.getRepeatEndData())))
                        && (reservation.getRoomName() == null || r.getRoomName().contains(reservation.getRoomName()))
                )
                .toList();
        // 分页
        int total = filteredReservations.size();
        int fromIndex = (pageNum - 1) * pageSize;
        int toIndex = Math.min(fromIndex + pageSize, total);
        List<Reservation> pageReservations = filteredReservations.subList(fromIndex, toIndex);

        // 将分页结果包装成ResultVo
        PageInfo<Reservation> pageInfo = new PageInfo<>(pageReservations);
        pageInfo.setTotal(total);
        return ResultVo.success(pageInfo);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public ResultVo<?> removeByReservationId(Long reservationId) {
        this.meetReservationService.removeById(reservationId);
        if (!this.removeById(reservationId)) {
            return ResultVo.failure(ResultCode.FAILED);
        }
        return ResultVo.success();
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public ResultVo<?> removeBatchReservation(List<Long> reservationIds) {
        System.out.println("+++++=====" + reservationIds);
        this.meetReservationService.removeBatchByIds(reservationIds);
        if (!this.removeBatchByIds(reservationIds)) {
            ResultVo.failure(ResultCode.FAILED);
        }
        return ResultVo.success();
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public ResultVo<?> edit(Long reservationId, String purpose, Long userId) {
        Reservation reservation = this.getById(reservationId);
        reservation.setPurpose(purpose);
        if (!this.updateById(reservation)) {
            return ResultVo.failure(ResultCode.FAILED);
        }
        MeetReservation meetReservation = this.meetReservationService.getOne(new QueryWrapper<MeetReservation>().lambda().eq(MeetReservation::getReservationId, reservationId));
        meetReservation.setUserId(userId);
        if (!this.meetReservationService.updateById(meetReservation)) {
            return ResultVo.failure(ResultCode.FAILED);
        }
        return ResultVo.success();
    }

    @Override
    public void exportReservation(HttpServletResponse response) {
        try {
            // 1. 查询预订信息
            List<Reservation> reservations = reservationListByUserId();
            List<ReservationExportDTO> exportData = reservations.stream()
                    .map(ReservationExportDTO::new)
                    .toList();
            // 2. 设置响应头
            String fileName = URLEncoder.encode("预约信息导出", StandardCharsets.UTF_8).replaceAll("\\+", "%20");
            response.setContentType("application/octet-stream;charset=utf-8");
            response.setHeader("Content-disposition", "attachment;filename*=utf-8''" + fileName + ".xlsx");
            // 3. 使用EasyExcel导出
            EasyExcel.write(response.getOutputStream(), ReservationExportDTO.class)
                    .excelType(ExcelTypeEnum.XLSX)
                    .sheet("预约信息")
                    .registerWriteHandler(new CustomCellWriteHeightConfig())
                    .registerWriteHandler(new CustomCellWriteWidthConfig())
                    .doWrite(exportData);
        } catch (Exception e) {
            e.printStackTrace();
            // 返回错误信息
            response.setContentType("text/plain;charset=utf-8");
            try {
                response.getWriter().write("导出失败：" + e.getMessage());
            } catch (IOException ioException) {
                ioException.printStackTrace();
            }
        }
    }

    public List<Reservation> reservationListByUserId() {
        long loginIdAsLong = StpUtil.getLoginIdAsLong();
        List<String> roleCodes = this.sysUserMapper.selectRoleCodesByUserId(loginIdAsLong);

        List<MeetReservation> meetReservations = getMeetReservationsByRole(loginIdAsLong, roleCodes);
        List<Long> reservationIds = extractReservationIds(meetReservations);

        if (reservationIds.isEmpty()) {
            return Collections.emptyList();
        }

        List<Reservation> reservations = this.listByIds(reservationIds);
        Map<Long, String> roomNameMap = getRoomNameMap(meetReservations);
        Map<Long, SysUser> userMap = getUserMap(meetReservations);

        return enrichReservations(reservations, meetReservations, roomNameMap, userMap);
    }

    private List<MeetReservation> getMeetReservationsByRole(long loginIdAsLong, List<String> roleCodes) {
        if (!roleCodes.contains("super_admin")) {
            return this.meetReservationService.list(new QueryWrapper<MeetReservation>().lambda()
                    .eq(MeetReservation::getUserId, loginIdAsLong));
        } else {
            return this.meetReservationService.list();
        }
    }

    private List<Long> extractReservationIds(List<MeetReservation> meetReservations) {
        return meetReservations.stream()
                .map(MeetReservation::getReservationId)
                .toList();
    }

    private Map<Long, String> getRoomNameMap(List<MeetReservation> meetReservations) {
        List<Long> roomIds = meetReservations.stream()
                .map(MeetReservation::getRoomId)
                .distinct()
                .toList();
        return this.meetingRoomsService.listByIds(roomIds).stream()
                .collect(Collectors.toMap(MeetingRooms::getRoomId, MeetingRooms::getRoomName));
    }

    private Map<Long, SysUser> getUserMap(List<MeetReservation> meetReservations) {
        List<Long> userIds = meetReservations.stream()
                .map(MeetReservation::getUserId)
                .distinct()
                .toList();
        return this.sysUserService.listByIds(userIds).stream()
                .collect(Collectors.toMap(SysUser::getUserId, user -> user));
    }

    private List<Reservation> enrichReservations(List<Reservation> reservations, List<MeetReservation> meetReservations, Map<Long, String> roomNameMap, Map<Long, SysUser> userMap) {
        for (Reservation reservation : reservations) {
            enrichReservationWithRoomInfo(reservation, meetReservations, roomNameMap);
            enrichReservationWithUserInfo(reservation, meetReservations, userMap);
        }
        return reservations;
    }

    private void enrichReservationWithRoomInfo(Reservation reservation, List<MeetReservation> meetReservations, Map<Long, String> roomNameMap) {
        meetReservations.stream()
                .filter(mr -> mr.getReservationId().equals(reservation.getReservationId()))
                .findFirst()
                .map(MeetReservation::getRoomId)
                .ifPresent(roomId -> reservation.setRoomName(roomNameMap.get(roomId)));
    }

    private void enrichReservationWithUserInfo(Reservation reservation, List<MeetReservation> meetReservations, Map<Long, SysUser> userMap) {
        meetReservations.stream()
                .filter(mr -> mr.getReservationId().equals(reservation.getReservationId()))
                .findFirst()
                .map(MeetReservation::getUserId)
                .ifPresent(userId -> {
                    SysUser user = userMap.get(userId);
                    if (user != null) {
                        reservation.setUserId(userId);
                        reservation.setUsername(user.getUsername());
                        reservation.setPhone(user.getPhone());
                    }
                });
    }
}